using System.ComponentModel.DataAnnotations;
using LuckyLang.AST.Expression.ValueTyre;

namespace LuckyLang.AST.Expression;
/// <summary>
/// opers: left (open) right
/// </summary>
public class Operation : Expression
{
    public Expression Left  { get; set; }
    public Expression Right { get; set; }
    public Lexer      Opers { get; set; }

    public Operation(Expression left,Lexer opers,Expression right)
    {
        Left  = left;
        Opers = opers;
        Right = right;
    }
    public override Value GetValue(ref VariateManager Manager)
    {
        var r = Right.GetValue(ref Manager);
        // not r
        if (Left is null && Opers == Lexer.NOT && r is BoolValue)
        {
            var a = r as BoolValue;
            return new BoolValue(a.Not());
        }
        var l = Left.GetValue(ref Manager);
        // l (+-* /) r
        if (l is not null && r is not null && Opers == Lexer.PLUS)
            return l.PlusValue(r);
        if (l is not null && r is not null && Opers == Lexer.MINUS)
            return l.MinusValue(r);
        if (l is not null && r is not null && Opers == Lexer.TIMES)
            return l.TimesValue(r);
        if (l is not null && r is not null && Opers == Lexer.DIVIDE)
            return l.DivideValue(r);
        // l.r
        if (l is not null && r is not null && Opers == Lexer.DOT)
            return l.Dot(r);
        // l (and,or) r
        if (l is BoolValue && r is BoolValue && Opers == Lexer.AND)
        {
            var r1 = r as BoolValue;
            var l1 = l as BoolValue;
            return new BoolValue(l1.And(r1));
        }
        if (l is BoolValue && r is BoolValue && Opers == Lexer.OR)
        {
            var r1 = r as BoolValue;
            var l1 = l as BoolValue;
            return new BoolValue(l1.Or(r1));
        }
        // l (<,>,<=,>=,==,!=) r
        if (l is not null && r is not null && Opers == Lexer.LESSER)
            return new BoolValue(l.LesserValue(r));
        if (l is not null && r is not null && Opers == Lexer.GREATER)
            return new BoolValue(l.GreaterValue(r));
        if (l is not null && r is not null && Opers == Lexer.LESS_EQ)
            return new BoolValue(l.LessEqValue(r));
        if (l is not null && r is not null && Opers == Lexer.GR_EQ)
            return new BoolValue(l.GreaEqValue(r));
        if (l is not null && r is not null && Opers == Lexer.EQUALS)
            return new BoolValue(l.EqualsValue(r));
        if (l is not null && r is not null && Opers == Lexer.DIFFERENT)
            return new BoolValue(l.DifferentValue(r));
        return null;
    }
    public override string ToString() => $" {Left} {Opers} {Right}";
}
